package com.wbihua.common.metrics.interceptor;

import com.wbihua.common.metrics.manager.MetricManager;
import com.wbihua.common.metrics.type.*;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


public class PrometheusMetricsInterceptor implements HandlerInterceptor {

    private final MetricManager metricManager;

    public PrometheusMetricsInterceptor(MetricManager metricManager){
        this.metricManager = metricManager;
    }
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String requestURI = request.getRequestURI();
        String method = request.getMethod();
        int status = response.getStatus();
        this.metricManager.getEventMeterGauge(EventGaugeType.INPROGRESS_REQUESTS).increment(1);
        this.metricManager.getEventMeterGauge(EventGaugeType.TAG_INPROGRESS_REQUESTS).increment(1, requestURI, method);
        this.metricManager.getEventMeterGauge(EventGaugeType.PROMETHEUS_INPROGRESS_REQUESTS).increment(1, requestURI, method);

        this.metricManager.getEventMeterTimer(EventTimerType.REQUEST_TIMER).startTimer(timer -> request.setAttribute(EventTimerType.REQUEST_TIMER.getName(), timer), requestURI, method, String.valueOf(status));

        this.metricManager.getEventMeterPrometheusHistogram(EventPrometheusHistogramType.PROMETHEUS_REQUEST_HISTOGRAM)
                .startTimer(timer -> request.setAttribute(EventPrometheusHistogramType.PROMETHEUS_REQUEST_HISTOGRAM.getName(), timer), requestURI, method, String.valueOf(status));
        this.metricManager.getEventMeterPrometheusSummary(EventPrometheusSummaryType.PROMETHEUS_REQUEST_SUMMARY)
                .startTimer(timer -> request.setAttribute(EventPrometheusSummaryType.PROMETHEUS_REQUEST_SUMMARY.getName(), timer), requestURI, method, String.valueOf(status));

        return HandlerInterceptor.super.preHandle(request, response, handler);
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        String requestURI = request.getRequestURI();
        String method = request.getMethod();
        int status = response.getStatus();
        //Counter
        this.metricManager.getEventMeterCounter(EventCounterType.REQUEST_TOTAL).increment(1);
        this.metricManager.getEventMeterCounter(EventCounterType.TAG_REQUEST_TOTAL).increment(1, requestURI, method, String.valueOf(status));
        this.metricManager.getEventMeterCounter(EventCounterType.PROMETHEUS_REQUEST_TOTAL).increment(1, requestURI, method, String.valueOf(status));
        //gauge
        this.metricManager.getEventMeterGauge(EventGaugeType.INPROGRESS_REQUESTS).decrement(1);
        this.metricManager.getEventMeterGauge(EventGaugeType.TAG_INPROGRESS_REQUESTS).decrement(1, requestURI, method);
        this.metricManager.getEventMeterGauge(EventGaugeType.PROMETHEUS_INPROGRESS_REQUESTS).decrement(1, requestURI, method);

        this.metricManager.getEventMeterTimer(EventTimerType.REQUEST_TIMER).stopTimer(() -> request.getAttribute(EventTimerType.REQUEST_TIMER.getName()), requestURI, method, String.valueOf(status));
        this.metricManager.getEventMeterSummary(EventSummaryType.REQUEST_STATUS_SUMMARY).record(status, requestURI, method, String.valueOf(status));

        this.metricManager.getEventMeterPrometheusHistogram(EventPrometheusHistogramType.PROMETHEUS_REQUEST_HISTOGRAM).observeDuration(() -> request.getAttribute(EventPrometheusHistogramType.PROMETHEUS_REQUEST_HISTOGRAM.getName()));
        this.metricManager.getEventMeterPrometheusSummary(EventPrometheusSummaryType.PROMETHEUS_REQUEST_SUMMARY).observeDuration(() -> request.getAttribute(EventPrometheusSummaryType.PROMETHEUS_REQUEST_SUMMARY.getName()));

        HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
    }
}
